package com.wyzz.hr.util.output;

import java.lang.reflect.Method;
import java.util.*;

import com.wyzz.hr.util.comparator.ObjectComparator;
import com.wyzz.hr.util.reflect.ObjectProperty;

public class Statistic {

	public Statistic() {
	}

	public Statistic(List listList, List groupPlaceList) {
		initList(listList, groupPlaceList);
	}

	public void initList(List listList, List groupPlaceList) {
		this.listList = listList;
		this.groupPlaceList = groupPlaceList;
	}

	public List statistic(String statisticMethod, int index) throws Exception {
		if (statisticMethod == null || statisticMethod.length() < 1) {
			return null;
		} else {
			Class parameterClass[] = { List.class, Integer.TYPE, List.class };
			Method method = Statistic.class.getMethod(statisticMethod,
					parameterClass);
			Object parameter[] = { listList, Integer.valueOf(index),
					groupPlaceList };
			return (List) method.invoke(this, parameter);
		}
	}

	public static List statistic(String statisticMethod, List list, int index,
			List groupPlaceList) throws Exception {
		if (statisticMethod == null || statisticMethod.length() < 1)
			return null;
		if (statisticMethod.compareTo("avg") == 0)
			return avg(list, index, groupPlaceList);
		if (statisticMethod.compareTo("sum") == 0)
			return sum(list, index, groupPlaceList);
		if (statisticMethod.compareTo("min") == 0)
			return min(list, index, groupPlaceList);
		if (statisticMethod.compareTo("max") == 0)
			return max(list, index, groupPlaceList);
		if (statisticMethod.compareTo("count") == 0)
			return count(list, index, groupPlaceList);
		if (statisticMethod.compareTo("mode") == 0)
			return mode(list, index, groupPlaceList);
		else
			return null;
	}

	public static List sum(List list, int index, List groupPlaceList)
			throws Exception {
		Method doubleMethod = null;
		for (int i = 0; i < list.size(); ++i) {
			Object obj = ((List) list.get(i)).get(index);
			if (obj != null) {
				doubleMethod = obj.getClass().getMethod("doubleValue",
						new Class[0]);
				break;
			}
		}
		if (doubleMethod == null) {
			return null;
		}
		int allNum = list.size();
		List result = new ArrayList();
		result.add(new ArrayList());
		for (int i = 1; i < ((List) groupPlaceList.get(0)).size(); ++i) {
			double sumTmp = 0.0D;
			for (int j = ((Integer) ((List) groupPlaceList.get(0)).get(i - 1))
					.intValue(); j < ((Integer) ((List) groupPlaceList.get(0))
					.get(i)).intValue(); ++j) {
				sumTmp += ObjectProperty.getObjectDoublelValue(((List) list
						.get(j)).get(index), doubleMethod);
			}
			((List) result.get(0)).add(Double.valueOf(sumTmp));
		}
		for (int i = 1; i < groupPlaceList.size(); ++i) {
			result.add(new ArrayList());
			int k = 0;
			for (int j = 1; j < ((List) groupPlaceList.get(i)).size(); ++j) {
				double sumTmp = 0.0D;
				int place0 = ((Integer) ((List) groupPlaceList.get(i - 1))
						.get(k)).intValue();
				int place1 = ((Integer) ((List) groupPlaceList.get(i)).get(j))
						.intValue();
				while (place0 < place1) {
					sumTmp += ((Double) ((List) result.get(i - 1)).get(k))
							.doubleValue();
					place0 = ((Integer) ((List) groupPlaceList.get(i - 1))
							.get(++k)).intValue();
				}
				((List) result.get(i)).add(Double.valueOf(sumTmp));
			}
		}
		return result;
	}

	public static List avg(List list, int index, List groupPlaceList)
			throws Exception {
		List result = sum(list, index, groupPlaceList);
		if (result == null)
			return null;
		for (int i = 0; i < groupPlaceList.size(); i++) {
			for (int j = 1; j < ((List) groupPlaceList.get(i)).size(); j++) {
				double avgTmp = ((Double) ((List) result.get(i)).get(j - 1))
						.doubleValue();
				avgTmp /= ((Integer) ((List) groupPlaceList.get(i)).get(j))
						.intValue()
						- ((Integer) ((List) groupPlaceList.get(i)).get(j - 1))
								.intValue();
				((List) result.get(i)).set(j - 1, Double.valueOf(avgTmp));
			}

		}

		return result;
	}

	public static List minOrMax(List list, int index, List groupPlaceList,
			boolean isMin[]) throws Exception {
		int order = 1;
		if (isMin.length > 0 && isMin[0])
			order = -1;
		ObjectComparator objComparator = new ObjectComparator(order, new int[0]);
		List result = new ArrayList();
		int allNum = list.size();
		result.add(new ArrayList());
		for (int i = 0; i < ((List) groupPlaceList.get(0)).size() - 1; i++) {
			Object minOrMaxTmp = ((List) list
					.get(((Integer) ((List) groupPlaceList.get(0)).get(i))
							.intValue())).get(index);
			for (int j = ((Integer) ((List) groupPlaceList.get(0)).get(i))
					.intValue() + 1; j < ((Integer) ((List) groupPlaceList
					.get(0)).get(i + 1)).intValue(); j++) {
				Object objTmp = ((List) list.get(j)).get(index);
				if (objComparator.compare(minOrMaxTmp, objTmp) > 0)
					minOrMaxTmp = objTmp;
			}

			((List) result.get(0)).add(minOrMaxTmp);
		}

		for (int i = 1; i < groupPlaceList.size(); i++) {
			result.add(new ArrayList());
			int k = 0;
			for (int j = 1; j < ((List) groupPlaceList.get(i)).size(); j++) {
				Object minOrMaxTmp = ((List) result.get(i - 1)).get(k);
				int place0 = ((Integer) ((List) groupPlaceList.get(i - 1))
						.get(k)).intValue();
				for (int place1 = ((Integer) ((List) groupPlaceList.get(i))
						.get(j)).intValue(); place0 < place1; place0 = ((Integer) ((List) groupPlaceList
						.get(i - 1)).get(++k)).intValue())
					if (objComparator.compare(minOrMaxTmp, ((List) result
							.get(i - 1)).get(k)) > 0)
						minOrMaxTmp = ((List) result.get(i - 1)).get(k);

				((List) result.get(i)).add(minOrMaxTmp);
			}

		}

		return result;
	}

	public static List min(List list, int index, List groupPlaceList)
			throws Exception {
		return minOrMax(list, index, groupPlaceList, new boolean[] { true });
	}

	public static List max(List list, int index, List groupPlaceList)
			throws Exception {
		return minOrMax(list, index, groupPlaceList, new boolean[0]);
	}

	public static List count(List list, int index, List groupPlaceList)
			throws Exception {
		List statisticList = new ArrayList();
		statisticList.add(new ArrayList());
		for (int i = 0; i < ((List) groupPlaceList.get(0)).size() - 1; i++) {
			Set setTmp = new HashSet();
			for (int j = ((Integer) ((List) groupPlaceList.get(0)).get(i))
					.intValue(); j < ((Integer) ((List) groupPlaceList.get(0))
					.get(i + 1)).intValue(); j++)
				setTmp.add(((List) list.get(j)).get(index));

			setTmp.remove(null);
			((List) statisticList.get(0)).add(setTmp);
		}

		for (int i = 1; i < groupPlaceList.size(); i++) {
			statisticList.add(new ArrayList());
			int k = 0;
			for (int j = 1; j < ((List) groupPlaceList.get(i)).size(); j++) {
				Set setTmp = new HashSet();
				int place0 = ((Integer) ((List) groupPlaceList.get(i - 1))
						.get(k)).intValue();
				for (int place1 = ((Integer) ((List) groupPlaceList.get(i))
						.get(j)).intValue(); place0 < place1; place0 = ((Integer) ((List) groupPlaceList
						.get(i - 1)).get(++k)).intValue())
					setTmp
							.addAll((Collection) ((List) statisticList
									.get(i - 1)).get(k));

				setTmp.remove(null);
				((List) statisticList.get(i)).add(setTmp);
			}

		}

		List result = new ArrayList();
		for (int i = 0; i < statisticList.size(); i++) {
			result.add(new ArrayList());
			for (int j = 0; j < ((List) statisticList.get(i)).size(); j++)
				((List) result.get(i)).add(Integer
						.valueOf(((Set) ((List) statisticList.get(i)).get(j))
								.size()));

		}

		return result;
	}

	public static List mode(List list, int index, List groupPlaceList)
			throws Exception {
		List result = new ArrayList();
		result.add(new ArrayList());
		List statisticList = new ArrayList();
		statisticList.add(new ArrayList());
		for (int i = 0; i < ((List) groupPlaceList.get(0)).size() - 1; i++) {
			Map mapTmp = new TreeMap();
			((List) statisticList.get(0)).add(mapTmp);
			int countMaxTmp = 0;
			Object objMaxTmp = null;
			for (int j = ((Integer) ((List) groupPlaceList.get(0)).get(i))
					.intValue(); j < ((Integer) ((List) groupPlaceList.get(0))
					.get(i + 1)).intValue(); j++) {
				Object objTmp = ((List) list.get(j)).get(index);
				if (objTmp == null)
					continue;
				int countTmp = 1;
				if (mapTmp.containsKey(objTmp))
					countTmp += ((Integer) mapTmp.get(objTmp)).intValue();
				mapTmp.put(objTmp, Integer.valueOf(countTmp));
				if (countTmp > countMaxTmp) {
					countMaxTmp = countTmp;
					objMaxTmp = objTmp;
				}
			}

			((List) result.get(0)).add(objMaxTmp);
		}

		for (int i = 1; i < groupPlaceList.size(); i++) {
			result.add(new ArrayList());
			statisticList.add(new ArrayList());
			int k = 0;
			for (int j = 1; j < ((List) groupPlaceList.get(i)).size(); j++) {
				Map mapTmp = new TreeMap();
				((List) statisticList.get(i)).add(mapTmp);
				Object objMaxTmp = null;
				int countMaxTmp = 0;
				int place0 = ((Integer) ((List) groupPlaceList.get(i - 1))
						.get(k)).intValue();
				label0: for (int place1 = ((Integer) ((List) groupPlaceList
						.get(i)).get(j)).intValue(); place0 < place1; place0 = ((Integer) ((List) groupPlaceList
						.get(i - 1)).get(++k)).intValue()) {
					Iterator i$ = ((Map) ((List) statisticList.get(i - 1))
							.get(k)).keySet().iterator();
					do {
						if (!i$.hasNext())
							continue label0;
						Object objTmp = i$.next();
						int countTmp = ((Integer) ((Map) ((List) statisticList
								.get(i - 1)).get(k)).get(objTmp)).intValue();
						if (mapTmp.containsKey(objTmp))
							countTmp += ((Integer) mapTmp.get(objTmp))
									.intValue();
						mapTmp.put(objTmp, Integer.valueOf(countTmp));
						if (countTmp > countMaxTmp) {
							countMaxTmp = countTmp;
							objMaxTmp = objTmp;
						}
					} while (true);
				}

				((List) result.get(i)).add(objMaxTmp);
			}

		}

		return result;
	}

	public List getListList() {
		return listList;
	}

	public List getGroupPlaceList() {
		return groupPlaceList;
	}

	public static final String _SUM = "sum";
	public static final String _AVG = "avg";
	public static final String _MIN = "min";
	public static final String _MAX = "max";
	public static final String _COUNT = "count";
	public static final String _MODE = "mode";
	private List listList;
	private List groupPlaceList;
}
